package de.dhbw.karlsruhe.picsim.model.memory.impl;

import de.dhbw.karlsruhe.picsim.codeimport.LSTLine;
import de.dhbw.karlsruhe.picsim.model.memory.CommandRegisterAddress;
import de.dhbw.karlsruhe.picsim.model.memory.OpCode;
import de.dhbw.karlsruhe.picsim.model.memory.ProgramMemory;
import de.dhbw.karlsruhe.picsim.util.impl.BitUtilities;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User: goesen
 * Date: Apr 12, 2010
 * Time: 2:54:08 PM
 */
public class ProgramMemoryImpl implements ProgramMemory {
    private static final Log log = LogFactory.getLog(ProgramMemoryImpl.class);
    private final Map<CommandRegisterAddress, OpCode> ourOpCodes;

    public ProgramMemoryImpl(final Iterator<? extends LSTLine> lines) {
        ourOpCodes = new HashMap<CommandRegisterAddress, OpCode>();
        while (lines.hasNext()) {
            final LSTLine lstLine = lines.next();
            final CommandRegisterAddress address = lstLine.getCommandRegisterNumber();
            if (address != null) {
                if (ourOpCodes.containsKey(address)) {
                    log.warn("duplicate number " + address);
                    log.warn("int value is " + address.asInteger());
                }
                ourOpCodes.put(address, lstLine.getOpCode());
            }
        }

        if (!ourOpCodes.containsKey(CommandRegisterAddressImpl.createUnSafe(0))) {
            log.warn("no valid opcode at 0");
        }
        if (log.isDebugEnabled()) {
            for (final Map.Entry<CommandRegisterAddress, OpCode> entry : ourOpCodes.entrySet()) {
                log.debug(entry.getKey() + "points to->" + entry.getValue());
                log.debug(Integer.toHexString(BitUtilities.fromLeastSignificantBitFirst(entry.getValue().getValue())));
            }
        }
    }

    @NotNull
    @Override
    public OpCode getOpCodeAt(@NotNull final CommandRegisterAddress address) {
        final OpCode opCode = ourOpCodes.get(address);
        if (opCode != null) {
            return opCode;
        } else {

            //  log.info("Requested Opcode is not initialized " + address);
            return OpCodeImpl.createOpCode(0);
        }
    }
}
